/**
 * Colony.java
 *
 * Roslan's Remake of MOO in 3D using Ardor3D
 * (C) 2011 Roslan Amir. All rights reserved.
 */

package com.roslan.games.moo3d.data;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ardor3d.math.MathUtils;
import com.roslan.games.moo3d.Base;

/**
 * Comments go here.
 * 
 * @author Roslan Amir
 * @version 1.0 - Jan 8, 2011
 */
public class Colony extends Star {

	/**
     * 
     */
	private static final Logger logger = LoggerFactory.getLogger(Base.class);

	/**
	 * Starting population of each home world. For Easy, Simple and Average difficulty, this is 50. For Hard and Impossible this is 40.
	 */
	private static final int HOMEWORLD_INITIAL_POPULATION_EASY = 50;
	private static final int HOMEWORLD_INITIAL_POPULATION_HARD = 40;

	/**
	 * Starting factory count of each home world.
	 */
	private static final int HOMEWORLD_INITIAL_FACTORIES = 30;

	/**
	 * Starting population of each new colony.
	 */
	private static final int COLONY_INITIAL_POPULATION = 2;

	/**
	 * How much production (in BC) a factory produces.
	 */
	private static final int PRODUCTION_PER_FACTORY = 1;

	/**
	 * Costs of each planetary shield level: 0=None, 1=Class V, 2=Class X, 3=Class XV, 4=Class XX.
	 */
	private static final int[] PLANETARY_SHIELD_COST = { 0, 3000, 6000, 12000, 24000 };

	/**
	 * Names of each planetary shield level: 0=None, 1=Class V, 2=Class X, 3=Class XV, 4=Class XX.
	 */
	private static final String[] PLANETARY_SHIELD_CLASS = { "", "V", "X", "XV", "XX" };

	/**
	 * The cost of an interstellar stargate.
	 */
//	private static final int STARGATE_COST = 3000;

	/**
	 * The current capacity (maximum possible population) of this colony, for example, after terraforming. Initially the same as the planet size.
	 */
	public int capacity;

	/**
	 * The current population of this colony.
	 */
	public int population;

	/**
	 * The number of missile bases operational.
	 */
	public int bases;

	/**
	 * The number of factories (fully completed) currently available on this colony.
	 */
	public int factories;

	/**
	 * The accumulated waste generated by this colony's factories.
	 */
	public double waste;

	/**
	 * The base production produced by this colony.
	 */
	public int baseProduction;

	/**
	 * The net production produced by this colony.
	 */
	public int netProduction;

	/**
	 * Total accumulated BC for ship production.
	 */
	private double accumulatedShipAllocation;

	/**
	 * Total accumulated BC for defense production.
	 */
	private double accumulatedDefenseAllocation;

	/**
	 * The percentage of partially completed factory on this colony (between 0 and 1 exclusive).
	 */
	private double partialFactories;

	/**
	 * Partially grown colonists (less than 1 million units).
	 */
	private double partialColonists;

	/**
	 * Total ship maintenance cost.
	 */
	private int totalShipMaintenance;

	/**
	 * Flag to indicate whether the slider for the Ship ratio is locked.
	 */
	public boolean lockedShip;

	/**
	 * Flag to indicate whether the slider for the Defense ratio is locked.
	 */
	public boolean lockedDefense;

	/**
	 * Flag to indicate whether the slider for the Industry ratio is locked.
	 */
	public boolean lockedIndustry;

	/**
	 * Flag to indicate whether the slider for the Ecology ratio is locked.
	 */
	public boolean lockedEcology;

	/**
	 * Flag to indicate whether the slider for the Research ratio is locked.
	 */
	public boolean lockedResearch;

	/**
	 * Percentage of actual production allocated for Ship building.
	 */
	public int shipRatio;

	/**
	 * Percentage of actual production allocated for Shield and Missile Bases building.
	 */
	public int defenseRatio;

	/**
	 * Percentage of actual production allocated for Factory building.
	 */
	public int industryRatio;

	/**
	 * Percentage of actual production allocated for ecology spending.
	 */
	public int ecologyRatio;

	/**
	 * Percentage of actual production allocated for research spending.
	 */
	public int researchRatio;

	/**
	 * The index into the ShipType array for this colony.
	 */
	private int shipTypeIndex;

	/**
	 * The current planetary shield level: 0=None, 1=Class V, 2=Class X, 3=Class XV, 4=Class XX
	 */
	private int shieldLevel;

	/**
	 * Textual representation of the ship allocation ratio.
	 */
	public transient String shipRatioText;

	/**
	 * Textual representation of the defense allocation ratio.
	 */
	public transient String defenseRatioText;

	/**
	 * Textual representation of the industry allocation ratio.
	 */
	public transient String industryRatioText;

	/**
	 * Textual representation of the ecology allocation ratio.
	 */
	public transient String ecologyRatioText;

	/**
	 * Textual representation of the research allocation ratio.
	 */
	public transient String researchRatioText;

	/**
	 * Textual representation of the ship building status.
	 */
	public transient String shipStatusText;

	/**
	 * Textual representation of the defense building status.
	 */
	public transient String defenseStatusText;

	/**
	 * Textual representation of the industry status.
	 */
	public transient String industryStatusText;

	/**
	 * Textual representation of the ecology status.
	 */
	public transient String ecologyStatusText;

	/**
	 * Textual representation of the research status.
	 */
	public transient String researchStatusText;

	/**
	 * Working variable for building text strings.
	 */
	private final transient StringBuilder sb = new StringBuilder();

	/**
	 * Constructor -- constructs a new <code>Colony</code> with the given indices.
	 * 
	 * @param starIndex - the index into the <code>STAR_NAMES</code> array for this star.
	 * @param colorIndex - the index into the <code>STAR_DESCRIPTION</code> array for this star.
	 */
	public Colony(int starIndex, int colorIndex) {
		super(starIndex, colorIndex);
	}

	/**
	 * Create a new <code>Colony</code> based on the given <code>Star</code> for the given race.
	 * 
	 * @param star - the star to colonize
	 * @param race - the race who owns this colony
	 */
	public static Colony createNewColony(Star star, Race race) {
		logger.info("Inside Colony.createNewColony: star = " + star + ", race = " + race);

		/*
		 * Create and initialize the colony's star's attributes.
		 */
		Colony colony = new Colony(star.starIndex, star.colorIndex);
		colony.name = star.name;
		colony.planetSize = star.planetSize;
		colony.environment = star.environment;
		colony.fertility = star.fertility;
		colony.minerals = star.minerals;
		colony.research = star.research;
		colony.bcPerProduction = star.bcPerProduction;
		colony.growthRate = star.growthRate;
		colony.rpPerProduction = star.rpPerProduction;
		colony.specials = star.specials;
		colony.explored = true;
		colony.owner = race;

		/*
		 * Initialize the new colony standard attributes.
		 */
		colony.population = Colony.COLONY_INITIAL_POPULATION;
		colony.factories = 0;
		colony.initColonyStandardAttributes();

		return colony;
	}

	/**
	 * Create the home world for the specified player or non-player race.
	 * 
	 * @param race - the race who owns this colony
	 * @param isEasy - <code>true</code> for EASY, SIMPLE and AVERAGE; <code>false</code> for HARD and IMPOSSIBLE
	 * @return the <code>Colony</code> object representing the home world of the specified race
	 */
	public static Colony createHomeWorld(Race race, boolean isEasy) {
		logger.info("Inside Colony.createHomeStar: race = " + race);

		/*
		 * Create and initialize the colony's star's attributes.
		 */
		Colony colony = new Colony(race.raceIndex + 1, 0); // orion's index = 0, the home worlds are 1-10, color is yellow for all home stars
		colony.planetSize = Star.HOMEWORLD_PLANET_SIZE;
		colony.environment = Environment.TERRAN;
		colony.fertility = Fertility.NORMAL;
		colony.minerals = Minerals.NORMAL;
		colony.research = Research.NORMAL;
		colony.bcPerProduction = Star.BC_PER_PRODUCTION_NORMAL;
		colony.growthRate = Star.GROWTH_RATE_NORMAL;
		colony.rpPerProduction = Star.RP_PER_PRODUCTION_NORMAL;
		colony.specials = colony.makeSpecials();
		colony.owner = race;
		colony.explored = true;

		/*
		 * Initialize the new colony standard attributes.
		 */
		colony.population = (isEasy) ? Colony.HOMEWORLD_INITIAL_POPULATION_EASY : Colony.HOMEWORLD_INITIAL_POPULATION_HARD;
		colony.factories = Colony.HOMEWORLD_INITIAL_FACTORIES;
		colony.initColonyStandardAttributes();

		return colony;
	}

	/**
	 * Initialize the new colony standard attributes.
	 */
	private void initColonyStandardAttributes() {
		/*
		 * Initialize the colony's attributes.
		 */
		this.capacity = this.planetSize;
		this.partialFactories = 0.0f;
		this.bases = 0;
		this.totalShipMaintenance = 12; // temporary

		/*
		 * Calculate the productions and waste.
		 */
		this.updateBaseProduction();
		this.updateNetProduction();
		this.waste = 0.0f;

		/*
		 * Allocate enough spending on Ecology to clean up the waste and the remainder on Industry.
		 */
		this.shipRatio = 0;
		this.defenseRatio = 0;
		this.ecologyRatio = this.calculateMinEcologyRatio();
		this.industryRatio = 100 - this.ecologyRatio;
		this.researchRatio = 0;

		/*
		 * Initialize the rest of the colony's allocation attributes.
		 */
		this.lockedShip = false;
		this.lockedDefense = false;
		this.lockedIndustry = false;
		this.lockedEcology = false;
		this.lockedResearch = false;
		this.accumulatedShipAllocation = 0.0f;
		this.accumulatedDefenseAllocation = 0.0f;
		this.partialColonists = 0.0f; // for population growth (initially 20BC to grow one population unit)

		/*
		 * Initialize the colony's other attributes.
		 */
		this.shipTypeIndex = 0; // first design = scout
		this.shieldLevel = 0; // no shield

		/*
		 * Update the production allocation texts
		 */
		this.updateShipText();
		this.updateDefenseText();
		this.updateIndustryText();
		this.updateEcologyText();
		this.updateResearchText();
		// this.updateSpacedockText();
	}

	/**
	 * Calculate and return the base production for this colony.
	 */
	public void updateBaseProduction() {
		int usableFactories = this.population * this.owner.factoriesPerPopulation;
		if (usableFactories > this.factories)
			usableFactories = this.factories;
		int productionFromFactories = usableFactories * Colony.PRODUCTION_PER_FACTORY;
		double productionFromPopulation = this.population * this.owner.productionPerPopulation;
		this.baseProduction = (int) (productionFromFactories + productionFromPopulation);
	}

	/**
	 * Calculate and return the net production for this colony.
	 */
	public void updateNetProduction() {
		this.netProduction = this.baseProduction - this.totalShipMaintenance;
	}

	/**
	 * Calculate and return the projected factory waste for this colony.
	 */
	private double calculateProjectedWaste() {
		int usableFactories = this.population * this.owner.factoriesPerPopulation;
		if (usableFactories > this.factories)
			usableFactories = this.factories;
		return usableFactories * this.owner.wastePerFactory;
	}

	/**
	 * Calculate the minimum ecology ratio to clean up the waste.
	 *
	 * @return the minimum ecology ratio to clean up the population
	 */
	private int calculateMinEcologyRatio() {
		double projectedWaste = this.calculateProjectedWaste() + this.waste;
		double cleanupCost = projectedWaste * this.owner.cleanupCostPerWaste;
		int ratio = (int) Math.ceil(cleanupCost * 100 / this.netProduction);
		return ratio;
	}

	/**
	 * Updates the textual representation for the ship ratio and status.
	 */
	public void updateShipText() {
		sb.setLength(0);
//		sb.append("[b]");
		sb.append(this.shipRatio);
		sb.append('%');
//		sb.append("[/b]");
		this.shipRatioText = sb.toString();

		if (this.shipRatio == 0) {
//			this.shipStatusText = "[b]None[/b]";
			this.shipStatusText = "None";
		} else {
			sb.setLength(0);
//			sb.append("[b]");
			int shipCost = this.owner.shipTypes[this.shipTypeIndex].cost;
			double currentAllocation = (this.netProduction * this.shipRatio / 100) * this.bcPerProduction;
			double credits = this.accumulatedShipAllocation + currentAllocation;
			if (credits < shipCost) {
				int turns = 1;
				while (credits < shipCost) {
					credits += currentAllocation;
					turns++;
				}
				sb.append(turns);
				sb.append(" turns");
			} else if (credits < shipCost * 2) {
				sb.append("1 turn");
			} else {
				/*
				 * Temporary. Instead of ships/turn should just say 1 turn but indicate the ship count on the spacedock
				 */
				sb.append(MathUtils.floor(credits / shipCost));
				sb.append("/turn");
			}
//			sb.append("[/b]");
			this.shipStatusText = sb.toString();
		}
	}

	/**
	 * Updates the textual representation for the defense ratio and status.
	 */
	public void updateDefenseText() {
		sb.setLength(0);
//		sb.append("[b]");
		sb.append(this.defenseRatio);
		sb.append('%');
//		sb.append("[/b]");
		this.defenseRatioText = sb.toString();

		if (this.defenseRatio == 0) {
//			this.defenseStatusText = "[b]None[/b]";
			this.defenseStatusText = "None";
		} else {
			sb.setLength(0);
//			sb.append("[b]");
			double currentAllocation = (this.netProduction * this.defenseRatio / 100) * this.bcPerProduction;
			double credits = this.accumulatedDefenseAllocation + currentAllocation;
			/*
			 * Build the shield. If leftover, also build bases.
			 */
			if (this.shieldLevel < this.owner.maxShieldLevel) {
				double shieldCost = Colony.PLANETARY_SHIELD_COST[this.owner.maxShieldLevel];
				if (credits < shieldCost) {
					sb.append("Shield");
//					sb.append("[/b]");
					this.defenseStatusText = sb.toString();
					return;
				}
				credits -= shieldCost;
			}
			/*
			 * Build bases.
			 */
			if (credits < this.owner.missileBaseCost) {
				int turns = 1;
				while (credits < this.owner.missileBaseCost) {
					credits += currentAllocation;
					turns++;
				}
				sb.append(turns);
				sb.append(" turns");
			} else if (credits < this.owner.missileBaseCost * 2) {
				sb.append("1 turn");
			} else {
				sb.append(MathUtils.floor(credits / this.owner.missileBaseCost));
				sb.append("/turn");
			}
//			sb.append("[/b]");
			this.defenseStatusText = sb.toString();
		}
	}

	/**
	 * Updates the textual representation for the industry ratio and status.
	 */
	public void updateIndustryText() {
		sb.setLength(0);
//		sb.append("[b]");
		sb.append(this.industryRatio);
		sb.append('%');
//		sb.append("[/b]");
		this.industryRatioText = sb.toString();

		if (this.industryRatio == 0) {
//			this.industryStatusText = "[b]None[/b]";
			this.industryStatusText = "None";
		} else {
			sb.setLength(0);
//			sb.append("[b]");
			int maxBuildableFactories = this.capacity * this.owner.factoriesPerPopulation; // maximum factories that can be built
			if (this.factories >= maxBuildableFactories) {
				sb.append("Reserves");
			} else {
				int maxOperableFactories = this.population * this.owner.factoriesPerPopulation; // maximum factories that can be operated by the current population
				double currentAllocation = (this.netProduction * this.industryRatio / 100) * this.bcPerProduction;
				double newFactories = currentAllocation / this.owner.factoryCost + this.partialFactories;
				if (newFactories >= maxOperableFactories) {
					sb.append("Maximum");
				} else {
//					int temp = (MathUtils.floor(newFactories * 10)) / 10; // ensure only 1 decimal place
//					sb.append(temp);
					sb.append(newFactories);
					int pos = sb.indexOf(".");
					if (pos >= 0 && sb.length() > pos + 3) {
						sb.setLength(pos + 3);
					}
					sb.append(" factories/turn");
				}
			}
//			sb.append("[/b]");
			this.industryStatusText = sb.toString();
		}
	}

	/**
	 * Updates the textual representation for the ecology ratio and status.
	 */
	public void updateEcologyText() {
		sb.setLength(0);
//		sb.append("[b]");
		sb.append(this.ecologyRatio);
		sb.append('%');
//		sb.append("[/b]");
		this.ecologyRatioText = sb.toString();

		double projectedWaste = this.waste + this.calculateProjectedWaste();
		if (this.ecologyRatio == 0) {
			if (projectedWaste == 0.0f) { // no waste (either no factories or factories don't pollute any more)
//				this.ecologyStatusText = "[b]None[/b]";
				this.ecologyStatusText = "None";
			} else {
//				this.ecologyStatusText = "[b][c=#a00]Waste[/c][/b]";
				this.ecologyStatusText = "[c=#a00]Waste[/c]";
			}
		} else {
			sb.setLength(0);
//			sb.append("[b]");
			double allocation = this.netProduction * this.ecologyRatio / 100;
			double cleanupCost = projectedWaste * this.owner.cleanupCostPerWaste;
			if (allocation < cleanupCost) {
				sb.append("[c=#a00]Waste[/c]");
			} else if (this.population == this.capacity) {
				sb.append("Clean");
			} else {
				allocation -= cleanupCost;
				allocation += this.partialColonists;
				if (allocation < this.owner.populationCost) {
					sb.append("Clean");
				} else {
					long addPop = MathUtils.floor(allocation / this.owner.populationCost);
					if (addPop > this.capacity - this.population)
						addPop = this.capacity - this.population;
					sb.append('+');
					sb.append(addPop);
					sb.append(" Population");
				}
			}
//			sb.append("[/b]");
			this.ecologyStatusText = sb.toString();
		}
	}

	/**
	 * Updates the textual representation for the research ratio and status.
	 */
	public void updateResearchText() {
		sb.setLength(0);
//		sb.append("[b]");
		sb.append(this.researchRatio);
		sb.append('%');
//		sb.append("[/b]");
		this.researchRatioText = sb.toString();

		sb.setLength(0);
//		sb.append("[b]");
		int rp = MathUtils.floor((this.netProduction * this.researchRatio / 100) * this.rpPerProduction);
		sb.append(rp);
		sb.append(" RP");
//		sb.append("[/b]");
		this.researchStatusText = sb.toString();
	}

	/**
	 * Reduce the ship ratio to 0%.
	 */
	public void minimizeShipRatio() {
		logger.info("Inside minimizeShipRatio");
		if (this.lockedShip || this.shipRatio == 0)
			return;
		if (!this.lockedDefense && this.defenseRatio <= 100 - this.shipRatio) {
			this.defenseRatio += this.shipRatio;
			this.shipRatio = 0;
			updateShipText();
			updateDefenseText();
			return;
		}
		if (!this.lockedIndustry && this.industryRatio <= 100 - this.shipRatio) {
			this.industryRatio += this.shipRatio;
			this.shipRatio = 0;
			updateShipText();
			updateIndustryText();
			return;
		}
		if (!this.lockedEcology && this.ecologyRatio <= 100 - this.shipRatio) {
			this.ecologyRatio += this.shipRatio;
			this.shipRatio = 0;
			updateShipText();
			updateEcologyText();
			return;
		}
		if (!this.lockedResearch && this.researchRatio <= 100 - this.shipRatio) {
			this.researchRatio += this.shipRatio;
			this.shipRatio = 0;
			updateShipText();
			updateResearchText();
			return;
		}
	}

	/**
	 * Decrease the ship ratio by 1%.
	 */
	public void decreaseShipRatio() {
		logger.info("Inside decreaseShipRatio");
		logger.info("lockedShip=" + this.lockedShip);
		logger.info("shipRatio=" + this.shipRatio);
		if (this.lockedShip || this.shipRatio == 0)
			return;
		if (!this.lockedDefense && this.defenseRatio < 100) {
			this.shipRatio--;
			this.defenseRatio++;
			updateShipText();
			updateDefenseText();
			return;
		}
		if (!this.lockedIndustry && this.industryRatio < 100) {
			this.shipRatio--;
			this.industryRatio++;
			updateShipText();
			updateIndustryText();
			return;
		}
		if (!this.lockedEcology && this.ecologyRatio < 100) {
			this.shipRatio--;
			this.ecologyRatio++;
			updateShipText();
			updateEcologyText();
			return;
		}
		if (!this.lockedResearch && this.researchRatio < 100) {
			this.shipRatio--;
			this.researchRatio++;
			updateShipText();
			updateResearchText();
			return;
		}
	}

	/**
	 * Increase the ship ratio by 1%.
	 */
	public void increaseShipRatio() {
		logger.info("Inside increaseShipRatio");
		logger.info("lockedShip=" + this.lockedShip);
		logger.info("shipRatio=" + this.shipRatio);
		if (this.lockedShip || this.shipRatio == 100)
			return;
		if (!this.lockedDefense && this.defenseRatio > 0) {
//			this.shipRatio += 2;
//			this.defenseRatio -= 2;
			this.shipRatio++;
			this.defenseRatio--;
			updateShipText();
			updateDefenseText();
			return;
		}
		if (!this.lockedIndustry && this.industryRatio > 0) {
//			this.shipRatio += 2;
//			this.industryRatio -= 2;
			this.shipRatio++;
			this.industryRatio--;
			updateShipText();
			updateIndustryText();
			return;
		}
		if (!this.lockedEcology && this.ecologyRatio > 0) {
//			this.shipRatio += 2;
//			this.ecologyRatio -= 2;
			this.shipRatio++;
			this.ecologyRatio--;
			updateShipText();
			updateEcologyText();
			return;
		}
		if (!this.lockedResearch && this.researchRatio > 0) {
//			this.shipRatio += 2;
//			this.researchRatio -= 2;
			this.shipRatio++;
			this.researchRatio--;
			updateShipText();
			updateResearchText();
			return;
		}
	}

	/**
	 * Increase the ship ratio as much as possible.
	 */
	public void maximizeShipRatio() {
		logger.info("Inside maximizeShipRatio");
		if (this.lockedShip || this.shipRatio == 100)
			return;
		if (!this.lockedDefense && this.defenseRatio > 0) {
			this.shipRatio += this.defenseRatio;
			this.defenseRatio = 0;
			updateShipText();
			updateDefenseText();
		}
		if (!this.lockedIndustry && this.industryRatio > 0) {
			this.shipRatio += this.industryRatio;
			this.industryRatio = 0;
			updateShipText();
			updateIndustryText();
		}
		if (!this.lockedEcology && this.ecologyRatio > 0) {
			this.shipRatio += this.ecologyRatio;
			this.ecologyRatio = 0;
			updateShipText();
			updateEcologyText();
		}
		if (!this.lockedResearch && this.researchRatio > 0) {
			this.shipRatio += this.researchRatio;
			this.researchRatio = 0;
			updateShipText();
			updateResearchText();
		}
	}

	/**
	 * Reduce the defense ratio to 0%.
	 */
	public void minimizeDefenseRatio() {
		logger.info("Inside minimizeDefenseRatio");
		if (this.lockedDefense || this.defenseRatio == 0)
			return;
		if (!this.lockedShip && this.shipRatio <= 100 - this.defenseRatio) {
			this.shipRatio += this.defenseRatio;
			this.defenseRatio = 0;
			updateShipText();
			updateDefenseText();
			return;
		}
		if (!this.lockedIndustry && this.industryRatio <= 100 - this.defenseRatio) {
			this.industryRatio += this.defenseRatio;
			this.defenseRatio = 0;
			updateDefenseText();
			updateIndustryText();
			return;
		}
		if (!this.lockedEcology && this.ecologyRatio <= 100 - this.defenseRatio) {
			this.ecologyRatio += this.defenseRatio;
			this.defenseRatio = 0;
			updateDefenseText();
			updateEcologyText();
			return;
		}
		if (!this.lockedResearch && this.researchRatio <= 100 - this.defenseRatio) {
			this.researchRatio += this.defenseRatio;
			this.defenseRatio = 0;
			updateDefenseText();
			updateResearchText();
			return;
		}
	}

	/**
	 * Decrease the defense ratio by 1%.
	 */
	public void decreaseDefenseRatio() {
		logger.info("Inside decreaseDefenseRatio");
		if (this.lockedDefense || this.defenseRatio == 0)
			return;
		if (!this.lockedShip && this.shipRatio < 100) {
//			this.defenseRatio -= 2;
//			this.shipRatio += 2;
			this.defenseRatio--;
			this.shipRatio++;
			updateDefenseText();
			updateShipText();
			return;
		}
		if (!this.lockedIndustry && this.industryRatio < 100) {
//			this.defenseRatio -= 2;
//			this.industryRatio += 2;
			this.defenseRatio--;
			this.industryRatio++;
			updateDefenseText();
			updateIndustryText();
			return;
		}
		if (!this.lockedEcology && this.ecologyRatio < 100) {
//			this.defenseRatio -= 2;
//			this.ecologyRatio += 2;
			this.defenseRatio--;
			this.ecologyRatio++;
			updateDefenseText();
			updateEcologyText();
			return;
		}
		if (!this.lockedResearch && this.researchRatio < 100) {
			this.defenseRatio -= 2;
			this.researchRatio += 2;
			updateDefenseText();
			updateResearchText();
			return;
		}
	}

	/**
	 * Increase the defense ratio by 1%.
	 */
	public void increaseDefenseRatio() {
		logger.info("Inside increaseDefenseRatio");
		if (this.lockedDefense || this.defenseRatio == 100)
			return;
		if (!this.lockedShip && this.shipRatio > 0) {
//			this.defenseRatio += 2;
//			this.shipRatio -= 2;
			this.defenseRatio++;
			this.shipRatio--;
			updateDefenseText();
			updateShipText();
			return;
		}
		if (!this.lockedIndustry && this.industryRatio > 0) {
//			this.defenseRatio += 2;
//			this.industryRatio -= 2;
			this.defenseRatio++;
			this.industryRatio--;
			updateDefenseText();
			updateIndustryText();
			return;
		}
		if (!this.lockedEcology && this.ecologyRatio > 0) {
//			this.defenseRatio += 2;
//			this.ecologyRatio -= 2;
			this.defenseRatio++;
			this.ecologyRatio--;
			updateDefenseText();
			updateEcologyText();
			return;
		}
		if (!this.lockedResearch && this.researchRatio > 0) {
//			this.defenseRatio += 2;
//			this.researchRatio -= 2;
			this.defenseRatio++;
			this.researchRatio--;
			updateDefenseText();
			updateResearchText();
			return;
		}
	}

	/**
	 * Increase the defense ratio as much as possible.
	 */
	public void maximizeDefenseRatio() {
		logger.info("Inside maximizeDefenseRatio");
		if (this.lockedDefense || this.defenseRatio == 100)
			return;
		if (!this.lockedShip && this.shipRatio > 0) {
			this.defenseRatio += this.shipRatio;
			this.shipRatio = 0;
			updateShipText();
			updateDefenseText();
		}
		if (!this.lockedIndustry && this.industryRatio > 0) {
			this.defenseRatio += this.industryRatio;
			this.industryRatio = 0;
			updateDefenseText();
			updateIndustryText();
		}
		if (!this.lockedEcology && this.ecologyRatio > 0) {
			this.defenseRatio += this.ecologyRatio;
			this.ecologyRatio = 0;
			updateDefenseText();
			updateEcologyText();
		}
		if (!this.lockedResearch && this.researchRatio > 0) {
			this.defenseRatio += this.researchRatio;
			this.researchRatio = 0;
			updateDefenseText();
			updateResearchText();
		}
	}

	/**
	 * Reduce the industry ratio to 0%.
	 */
	public void minimizeIndustryRatio() {
		logger.info("Inside minimizeIndustryRatio");
		if (this.lockedIndustry || this.industryRatio == 0)
			return;
		if (!this.lockedShip && this.shipRatio <= 100 - this.industryRatio) {
			this.shipRatio += this.industryRatio;
			this.industryRatio = 0;
			updateShipText();
			updateIndustryText();
			return;
		}
		if (!this.lockedDefense && this.defenseRatio <= 100 - this.industryRatio) {
			this.defenseRatio += this.industryRatio;
			this.industryRatio = 0;
			updateDefenseText();
			updateIndustryText();
			return;
		}
		if (!this.lockedEcology && this.ecologyRatio <= 100 - this.industryRatio) {
			this.ecologyRatio += this.industryRatio;
			this.industryRatio = 0;
			updateIndustryText();
			updateEcologyText();
			return;
		}
		if (!this.lockedResearch && this.researchRatio <= 100 - this.industryRatio) {
			this.researchRatio += this.industryRatio;
			this.industryRatio = 0;
			updateIndustryText();
			updateResearchText();
			return;
		}
	}

	/**
	 * Decrease the industry ratio by 1%.
	 */
	public void decreaseIndustryRatio() {
		logger.info("Inside decreaseIndustryRatio");
		if (this.lockedIndustry || this.industryRatio == 0)
			return;
		if (!this.lockedShip && this.shipRatio < 100) {
//			this.industryRatio -= 2;
//			this.shipRatio += 2;
			this.industryRatio--;
			this.shipRatio++;
			updateIndustryText();
			updateShipText();
			return;
		}
		if (!this.lockedDefense && this.defenseRatio < 100) {
//			this.industryRatio -= 2;
//			this.defenseRatio += 2;
			this.industryRatio--;
			this.defenseRatio++;
			updateIndustryText();
			updateDefenseText();
			return;
		}
		if (!this.lockedEcology && this.ecologyRatio < 100) {
//			this.industryRatio -= 2;
//			this.ecologyRatio += 2;
			this.industryRatio--;
			this.ecologyRatio++;
			updateIndustryText();
			updateEcologyText();
			return;
		}
		if (!this.lockedResearch && this.researchRatio < 100) {
//			this.industryRatio -= 2;
//			this.researchRatio += 2;
			this.industryRatio--;
			this.researchRatio++;
			updateIndustryText();
			updateResearchText();
			return;
		}
	}

	/**
	 * Increase the industry ratio by 1%.
	 */
	public void increaseIndustryRatio() {
		logger.info("Inside increaseIndustryRatio");
		if (this.lockedIndustry || this.industryRatio == 100)
			return;
		if (!this.lockedShip && this.shipRatio > 0) {
//			this.industryRatio += 2;
//			this.shipRatio -= 2;
			this.industryRatio++;
			this.shipRatio--;
			updateIndustryText();
			updateShipText();
			return;
		}
		if (!this.lockedDefense && this.defenseRatio > 0) {
//			this.industryRatio += 2;
//			this.defenseRatio -= 2;
			this.industryRatio++;
			this.defenseRatio--;
			updateIndustryText();
			updateDefenseText();
			return;
		}
		if (!this.lockedEcology && this.ecologyRatio > 0) {
//			this.industryRatio += 2;
//			this.ecologyRatio -= 2;
			this.industryRatio++;
			this.ecologyRatio--;
			updateIndustryText();
			updateEcologyText();
			return;
		}
		if (!this.lockedResearch && this.researchRatio > 0) {
//			this.industryRatio += 2;
//			this.researchRatio -= 2;
			this.industryRatio++;
			this.researchRatio--;
			updateIndustryText();
			updateResearchText();
			return;
		}
	}

	/**
	 * Increase the industry ratio as much as possible.
	 */
	public void maximizeIndustryRatio() {
		logger.info("Inside maximizeIndustryRatio");
		if (this.lockedIndustry || this.industryRatio == 100)
			return;
		if (!this.lockedShip && this.shipRatio > 0) {
			this.industryRatio += this.shipRatio;
			this.shipRatio = 0;
			updateShipText();
			updateIndustryText();
		}
		if (!this.lockedDefense && this.defenseRatio > 0) {
			this.industryRatio += this.defenseRatio;
			this.defenseRatio = 0;
			updateDefenseText();
			updateIndustryText();
		}
		if (!this.lockedEcology && this.ecologyRatio > 0) {
			this.industryRatio += this.ecologyRatio;
			this.ecologyRatio = 0;
			updateIndustryText();
			updateEcologyText();
		}
		if (!this.lockedResearch && this.researchRatio > 0) {
			this.industryRatio += this.researchRatio;
			this.researchRatio = 0;
			updateIndustryText();
			updateResearchText();
		}
	}

	/**
	 * Reduce the ecology ratio to 0%.
	 */
	public void minimizeEcologyRatio() {
		logger.info("Inside minimizeEcologyRatio");
		if (this.lockedEcology || this.ecologyRatio == 0)
			return;
		if (!this.lockedShip && this.shipRatio <= 100 - this.ecologyRatio) {
			this.shipRatio += this.ecologyRatio;
			this.ecologyRatio = 0;
			updateShipText();
			updateEcologyText();
			return;
		}
		if (!this.lockedDefense && this.defenseRatio <= 100 - this.ecologyRatio) {
			this.defenseRatio += this.ecologyRatio;
			this.ecologyRatio = 0;
			updateDefenseText();
			updateEcologyText();
			return;
		}
		if (!this.lockedIndustry && this.industryRatio <= 100 - this.ecologyRatio) {
			this.industryRatio += this.ecologyRatio;
			this.ecologyRatio = 0;
			updateIndustryText();
			updateEcologyText();
			return;
		}
		if (!this.lockedResearch && this.researchRatio <= 100 - this.ecologyRatio) {
			this.researchRatio += this.ecologyRatio;
			this.ecologyRatio = 0;
			updateEcologyText();
			updateResearchText();
			return;
		}
	}

	/**
	 * Decrease the ecology ratio by 1%.
	 */
	public void decreaseEcologyRatio() {
		logger.info("Inside decreaseEcologyRatio");
		if (this.lockedEcology || this.ecologyRatio == 0)
			return;
		if (!this.lockedShip && this.shipRatio < 100) {
//			this.ecologyRatio -= 2;
//			this.shipRatio += 2;
			this.ecologyRatio--;
			this.shipRatio++;
			updateEcologyText();
			updateShipText();
			return;
		}
		if (!this.lockedDefense && this.defenseRatio < 100) {
//			this.ecologyRatio -= 2;
//			this.defenseRatio += 2;
			this.ecologyRatio--;
			this.defenseRatio++;
			updateEcologyText();
			updateDefenseText();
			return;
		}
		if (!this.lockedIndustry && this.industryRatio < 100) {
//			this.ecologyRatio -= 2;
//			this.industryRatio += 2;
			this.ecologyRatio--;
			this.industryRatio++;
			updateEcologyText();
			updateIndustryText();
			return;
		}
		if (!this.lockedResearch && this.researchRatio < 100) {
//			this.ecologyRatio -= 2;
//			this.researchRatio += 2;
			this.ecologyRatio--;
			this.researchRatio++;
			updateEcologyText();
			updateResearchText();
			return;
		}
	}

	/**
	 * Increase the ecology ratio by 1%.
	 */
	public void increaseEcologyRatio() {
		logger.info("Inside increaseEcologyRatio");
		if (this.lockedEcology || this.ecologyRatio == 100)
			return;
		if (!this.lockedShip && this.shipRatio > 0) {
//			this.ecologyRatio += 2;
//			this.shipRatio -= 2;
			this.ecologyRatio++;
			this.shipRatio--;
			updateEcologyText();
			updateShipText();
			return;
		}
		if (!this.lockedDefense && this.defenseRatio > 0) {
//			this.ecologyRatio += 2;
//			this.defenseRatio -= 2;
			this.ecologyRatio++;
			this.defenseRatio--;
			updateEcologyText();
			updateDefenseText();
			return;
		}
		if (!this.lockedIndustry && this.industryRatio > 0) {
//			this.ecologyRatio += 2;
//			this.industryRatio -= 2;
			this.ecologyRatio++;
			this.industryRatio--;
			updateEcologyText();
			updateIndustryText();
			return;
		}
		if (!this.lockedResearch && this.researchRatio > 0) {
//			this.ecologyRatio += 2;
//			this.researchRatio -= 2;
			this.ecologyRatio++;
			this.researchRatio--;
			updateEcologyText();
			updateResearchText();
			return;
		}
	}

	/**
	 * Increase the ecology ratio as much as possible.
	 */
	public void maximizeEcologyRatio() {
		logger.info("Inside maximizeEcologyRatio");
		if (this.lockedEcology || this.ecologyRatio == 100)
			return;
		if (!this.lockedShip && this.shipRatio > 0) {
			this.ecologyRatio += this.shipRatio;
			this.shipRatio = 0;
			updateShipText();
			updateEcologyText();
		}
		if (!this.lockedDefense && this.defenseRatio > 0) {
			this.ecologyRatio += this.defenseRatio;
			this.defenseRatio = 0;
			updateDefenseText();
			updateEcologyText();
		}
		if (!this.lockedIndustry && this.industryRatio > 0) {
			this.ecologyRatio += this.industryRatio;
			this.industryRatio = 0;
			updateIndustryText();
			updateEcologyText();
		}
		if (!this.lockedResearch && this.researchRatio > 0) {
			this.ecologyRatio += this.researchRatio;
			this.researchRatio = 0;
			updateEcologyText();
			updateResearchText();
		}
	}

	/**
	 * Reduce the research ratio to 0%.
	 */
	public void minimizeResearchRatio() {
		logger.info("Inside minimizeResearchRatio");
		if (this.lockedResearch || this.researchRatio == 0)
			return;
		if (!this.lockedShip && this.shipRatio <= 100 - this.researchRatio) {
			this.shipRatio += this.researchRatio;
			this.researchRatio = 0;
			updateShipText();
			updateResearchText();
			return;
		}
		if (!this.lockedDefense && this.defenseRatio <= 100 - this.researchRatio) {
			this.defenseRatio += this.researchRatio;
			this.researchRatio = 0;
			updateDefenseText();
			updateResearchText();
			return;
		}
		if (!this.lockedIndustry && this.industryRatio <= 100 - this.researchRatio) {
			this.industryRatio += this.researchRatio;
			this.researchRatio = 0;
			updateIndustryText();
			updateResearchText();
			return;
		}
		if (!this.lockedEcology && this.ecologyRatio <= 100 - this.researchRatio) {
			this.ecologyRatio += this.researchRatio;
			this.researchRatio = 0;
			updateEcologyText();
			updateResearchText();
			return;
		}
	}

	/**
	 * Decrease the research ratio by 1%.
	 */
	public void decreaseResearchRatio() {
		logger.info("Inside decreaseResearchRatio");
		if (!this.lockedShip && this.shipRatio < 100) {
//			this.researchRatio -= 2;
//			this.shipRatio += 2;
			this.researchRatio--;
			this.shipRatio++;
			updateResearchText();
			updateShipText();
			return;
		}
		if (this.lockedResearch || this.researchRatio == 0)
			return;
		if (!this.lockedDefense && this.defenseRatio < 100) {
//			this.researchRatio -= 2;
//			this.defenseRatio += 2;
			this.researchRatio--;
			this.defenseRatio++;
			updateResearchText();
			updateDefenseText();
			return;
		}
		if (!this.lockedIndustry && this.industryRatio < 100) {
//			this.researchRatio -= 2;
//			this.industryRatio += 2;
			this.researchRatio--;
			this.industryRatio++;
			updateResearchText();
			updateIndustryText();
			return;
		}
		if (!this.lockedEcology && this.ecologyRatio < 100) {
//			this.researchRatio -= 2;
//			this.ecologyRatio += 2;
			this.researchRatio--;
			this.ecologyRatio++;
			updateResearchText();
			updateEcologyText();
			return;
		}
	}

	/**
	 * Increase the research ratio by 1%.
	 */
	public void increaseResearchRatio() {
		logger.info("Inside increaseResearchRatio");
		if (this.lockedResearch || this.researchRatio == 100)
			return;
		if (!this.lockedShip && this.shipRatio > 0) {
//			this.researchRatio += 2;
//			this.shipRatio -= 2;
			this.researchRatio++;
			this.shipRatio--;
			updateResearchText();
			updateShipText();
			return;
		}
		if (!this.lockedDefense && this.defenseRatio > 0) {
//			this.researchRatio += 2;
//			this.defenseRatio -= 2;
			this.researchRatio++;
			this.defenseRatio--;
			updateResearchText();
			updateDefenseText();
			return;
		}
		if (!this.lockedIndustry && this.industryRatio > 0) {
//			this.researchRatio += 2;
//			this.industryRatio -= 2;
			this.researchRatio++;
			this.industryRatio--;
			updateResearchText();
			updateIndustryText();
			return;
		}
		if (!this.lockedEcology && this.ecologyRatio > 0) {
//			this.researchRatio += 2;
//			this.ecologyRatio -= 2;
			this.researchRatio++;
			this.ecologyRatio--;
			updateResearchText();
			updateEcologyText();
			return;
		}
	}

	/**
	 * Increase the research ratio as much as possible.
	 */
	public void maximizeResearchRatio() {
		logger.info("Inside maximizeResearchRatio");
		if (this.lockedResearch || this.researchRatio == 100)
			return;
		if (!this.lockedShip && this.shipRatio > 0) {
			this.researchRatio += this.shipRatio;
			this.shipRatio = 0;
			updateShipText();
			updateResearchText();
		}
		if (!this.lockedDefense && this.defenseRatio > 0) {
			this.researchRatio += this.defenseRatio;
			this.defenseRatio = 0;
			updateDefenseText();
			updateResearchText();
		}
		if (!this.lockedIndustry && this.industryRatio > 0) {
			this.researchRatio += this.industryRatio;
			this.industryRatio = 0;
			updateIndustryText();
			updateResearchText();
		}
		if (!this.lockedEcology && this.ecologyRatio > 0) {
			this.researchRatio += this.ecologyRatio;
			this.ecologyRatio = 0;
			updateEcologyText();
			updateResearchText();
		}
	}

	/**
	 * Change the ship type currently being built in the spacedock.
	 */
	public void changeSpacedockShip() {
		do {
			this.shipTypeIndex++;
			if (this.shipTypeIndex == ShipType.TYPE_COUNT)
				this.shipTypeIndex = 0;
		} while (this.owner.shipTypes[this.shipTypeIndex] == null);
		updateShipText();
	}

	/**
	 * Returns the name of the ship type currently being built in the spacedock.
	 *
	 * @return the ship type name
	 */
	public String getShipTypeName() {
		return this.owner.shipTypes[this.shipTypeIndex].name;
	}

	/**
	 * Returns the name of the current shield class for this colony.
	 *
	 * @return the shield class
	 */
	public String getShieldClass() {
		return Colony.PLANETARY_SHIELD_CLASS[this.shieldLevel];
	}

//	/**
//	 * Updates the production for this colony when the player presses the NEXT TURN button.
//	 */
//	public void update() {
//		/*
//		 * Perform the spending on each of the areas.
//		 */
//		int ships = doShipSpending();
//		doDefenseSpending();
//		doIndustrySpending();
//		doEcologySpending();
//		doResearchSpending();
//
////		/*
////		 * If too low is allocated for Ecology, adjust it just enough to cleanup the waste.
////		 */
////		int minEcologyRatio = getMinEcologyRatio();
////		if (this.ecologyRatio < minEcologyRatio)
////			this.ecologyRatio = minEcologyRatio;
//
//		/*
//		 * Adjust the research ratio since some ratios may be changed during spending calculations.
//		 */
//		this.researchRatio = 100 - (this.shipRatio + this.defenseRatio + this.industryRatio + this.ecologyRatio);
//
//		/*
//		 * Update the new production values accordingly.
//		 */
//		this.updateBaseProduction();
//		this.updateNetProduction;
//
//		/*
//		 * Update the production allocation texts.
//		 */
//		updateShipText();
//		updateDefenseText();
//		updateIndustryText();
//		updateEcologyText();
//		updateResearchText();
//		// updateSpacedockText();
//	}

	/**
	 * Calculate the progress towards building ships or stargate for this turn.
	 *
	 * @return the number of ships/stargate built.
	 */
	public int doShipSpending() {
		if (this.shipRatio == 0)
			return 0;

		int shipCost = this.owner.shipTypes[this.shipTypeIndex].cost;

		/*
		 * Add to the total being spent on ship production.
		 */
		this.accumulatedShipAllocation += (this.netProduction * this.shipRatio / 100.0) * this.bcPerProduction;

		/*
		 * No ship built.
		 */
		if (this.accumulatedShipAllocation < shipCost) {
			return 0;
		}

		/*
		 * Enough spent to build 1 ship.
		 */
		if (this.accumulatedShipAllocation < shipCost * 2) {
			logger.info(this.name + " builds 1 ship: " + this.owner.shipTypes[this.shipTypeIndex].name);
			this.accumulatedShipAllocation -= shipCost;
			return 1;
		}

		/*
		 * More than 1 ship built.
		 */
		int ships = (int) (this.accumulatedShipAllocation / shipCost);
		logger.info(this.name + " builds " + ships + " ships: " + this.owner.shipTypes[this.shipTypeIndex].name);
		this.accumulatedShipAllocation -= shipCost * ships;
		return ships;
	}

	/**
	 * Calculate the progress towards building shields and missile bases for this turn.
	 */
	public void doDefenseSpending() {
		if (this.defenseRatio == 0)
			return;

		/*
		 * Add to the total being spent on defense production.
		 */
		this.accumulatedDefenseAllocation += (this.netProduction * this.defenseRatio / 100.0) * this.bcPerProduction;

		/*
		 * Colony's shield level is less than the Race's shield technology level.
		 */
		while (this.shieldLevel < this.owner.maxShieldLevel) {
			/*
			 * Not enough to complete the shield.
			 */
			if (this.accumulatedDefenseAllocation < Colony.PLANETARY_SHIELD_COST[this.shieldLevel + 1]) {
				return;
			}

			/*
			 * Next higher level Shield completed.
			 */
			this.shieldLevel++;
			logger.info(this.name + " builds planetary shield Class " + Colony.PLANETARY_SHIELD_CLASS[this.shieldLevel]);
			this.accumulatedDefenseAllocation -= Colony.PLANETARY_SHIELD_COST[this.shieldLevel];
		}
		this.defenseRatio = 0; // no need to allocate any more for defense

		/*
		 * No missile bases built.
		 */
		if (this.accumulatedDefenseAllocation < this.owner.missileBaseCost) {
			return;
		}

		/*
		 * 1 missile base built.
		 */
		if (this.accumulatedDefenseAllocation < this.owner.missileBaseCost * 2) {
			logger.info(this.name + " builds 1 missile base");
			this.accumulatedDefenseAllocation -= this.owner.missileBaseCost;
			this.bases++;
			return;
		}

		/*
		 * More than 1 missile bases built.
		 */
		int newBases = (int) (this.accumulatedDefenseAllocation / this.owner.missileBaseCost);
		logger.info(this.name + " builds " + newBases + " missile bases");
		this.accumulatedDefenseAllocation -= this.owner.missileBaseCost * newBases;
		this.bases += newBases;
	}

	/**
	 * Calculate the progress towards building factories for this turn.
	 */
	public void doIndustrySpending() {
		if (this.industryRatio == 0)
			return;

		/*
		 * Maximum number of factories that can be built for this colony.
		 */
		int maxBuildableFactories = this.capacity * this.owner.factoriesPerPopulation;

		/*
		 * Calculate the total being spent on industry production.
		 */
		double currentAllocation = (double) ((this.netProduction * this.industryRatio / 100.0) * this.bcPerProduction); // no accumulated allocation, any excess goes to the treasury.

		/*
		 * Factories already at maximum level, all allocation goes to the treasury.
		 */
		if (this.factories >= maxBuildableFactories) {
			this.owner.currentTreasury += MathUtils.floor(currentAllocation);
			return;
		}

		/*
		 * Build factories.
		 */
		double newFactories = currentAllocation / this.owner.factoryCost + this.partialFactories;
		if (newFactories + this.factories < maxBuildableFactories) {
			long completedFactories = MathUtils.floor(newFactories);
			this.factories += completedFactories;
			this.partialFactories = newFactories - completedFactories;
		}

		/*
		 * Maximum factories built. Extra credits go into the treasury.
		 */
		else {
			int builtFactories = maxBuildableFactories - this.factories;
			this.factories = maxBuildableFactories;
			this.partialFactories = 0.0f;
			int cost = builtFactories * this.owner.factoryCost;
			long excess = MathUtils.floor(currentAllocation - cost);
			this.owner.currentTreasury += excess;
			this.industryRatio = 0; // reset ratio since no more factories can be built
		}
	}

	/**
	 * Calculate the progress towards increasing the population for this turn. This is done after some production is used for cleanup.
	 */
	public void doEcologySpending() {
		if (this.ecologyRatio == 0)
			return;

		/*
		 * Calculate the BC being spent on ecology.
		 */
		double currentAllocation = (double) (this.netProduction * this.ecologyRatio / 100.0);

		/*
		 * Calculate the amount of waste generated (this includes the currently accumulated waste.)
		 */
		this.waste += this.calculateProjectedWaste();

		/*
		 * Not enough or just enough to clean up. Still some waste left over.
		 */
		double cleanupCost = this.waste * this.owner.cleanupCostPerWaste;
		if (currentAllocation <= cleanupCost) {
			cleanupCost -= currentAllocation;
			this.waste = cleanupCost / this.owner.cleanupCostPerWaste; // remaining waste still to clean up
			return;
		}

		/*
		 * Left over after cleanup and no more waste.
		 */
		currentAllocation -= cleanupCost;
		this.waste = 0.0f;

		/*
		 * Population is already maximized. Just discard the leftover BC.
		 */
		if (this.population == this.capacity) {
			this.partialColonists = 0.0f;
		}

		/*
		 * Add to the accumulated colonists being grown.
		 */
		else {
			this.partialColonists += currentAllocation / this.owner.populationCost;
		}

//		/*
//		 * Not enough to grow.
//		 */
//		if (currentAllocation < this.owner.populationCost)
//			return;

//		/*
//		 * Grow one or more colonists.
//		 */
//		while (currentAllocation >= this.owner.populationCost) {
//			this.population++;
//			currentAllocation -= this.owner.populationCost;
//			/*
//			 * Maximum population reached. Reduce Ecology spending to just enough to clean up.
//			 */
//			if (this.population == this.capacity) {
//				this.owner.currentTreasury += currentAllocation;
//				currentAllocation = 0;
//				this.ecologyRatio = 0;
//				break;
//			}
//		}
	}

	/**
	 * Calculate the progress towards achieving success on the research projects.
	 */
	public void doResearchSpending() {
		if (this.researchRatio == 0)
			return;

		/*
		 * For the moment, just accumulate the spending.
		 */
		this.owner.totalResearchPoints += (this.netProduction * this.researchRatio / 100) * this.rpPerProduction;
	}

	/*
	 * Constants used to calculate the population growth based on normal distribution.
	 */
	private static final double DENOMINATOR = Math.sqrt(Math.PI * 2);
	private static final double minFx = Math.pow(Math.E, -0.125) / DENOMINATOR;
	private static final double maxFx = Math.pow(Math.E, 0.0) / DENOMINATOR;

	/**
	 * Calculate the population growth for this colony.
	 */
	public void doPopulationGrowth() {
		logger.info("Inside doPopulationGrowth");
		/*
		 * Calculate the percentage of population growth using normal distribution and the current population.
		 */
		double x = ((double) this.population / (double) this.capacity) - 0.5f;
//		logger.info("x = " + x);
		double fx = (double) (Math.pow(Math.E, -((x * x) / 2)) / DENOMINATOR);
//		logger.info("fx = " + fx);
		double percent = (double) (((fx - minFx) / (maxFx - minFx)) * 3.0f); // 0.5f
//		logger.info("percent = " + percent);
		double newColonists = (double) (percent * this.capacity * this.growthRate / 100.0); // number of colonists grown naturally by this colony
//		logger.info("newColonists = " + newColonists);
		this.partialColonists += newColonists;
//		logger.info("partialColonists = " + partialColonists);
		long completedColonists = MathUtils.floor(newColonists);
//		logger.info("completedColonists = " + completedColonists);
		this.partialColonists -= completedColonists; // leftover
//		logger.info("partialColonists = " + partialColonists);
		this.population += completedColonists;
		logger.info("new population = " + population);
		if (this.population > this.capacity) {
			double excess = this.partialColonists + this.population - this.capacity;
			this.population = this.capacity;
			this.partialColonists = 0;
			this.owner.currentTreasury += excess * this.owner.populationCost;
			logger.info("Inside Colony.doPopulationGrowth: maximum population reached: " + this.population);
		}
		logger.info("Leaving doPopulationGrowth");
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return super.toString() + 
			" Colony [capacity=" + this.capacity + 
			", population=" + this.population + 
			", bases=" + this.bases + 
			", factories=" + this.factories + 
			", waste=" + this.waste + 
			", baseProduction=" + this.baseProduction + 
			", netProduction=" + this.netProduction + 
			", shipRatio=" + this.shipRatio + 
			", defenseRatio=" + this.defenseRatio + 
			", industryRatio=" + this.industryRatio + 
			", ecologyRatio=" + this.ecologyRatio + 
			", researchRatio=" + this.researchRatio + "]";
	}

}
